﻿using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace SharePointUtilitiesForDevelopers.Tests
{
    /// <summary>
    /// Test class for <see cref="SharePointFieldExtensionMethods"/>.
    /// </summary>
    [TestClass]
    public class SharePointFieldExtensionMethodsTest
    {
        [TestMethod]
        public void RemoveFieldsNotInList_removes_items_not_in_list()
        {
            var fields = new List<SharePointField>
                             {new SharePointField {StaticName = "Title"}, new SharePointField {StaticName = "ID"}};
            var fieldNames = new List<string> {"Title", "ID", "ExtraField"};

            var result = fieldNames.RemoveFieldsNotInList(fields).ToList();

            Assert.AreEqual(2, result.Count());
            Assert.AreEqual("Title", result[0]);
            Assert.AreEqual("ID", result[1]);
        }

        [TestMethod]
        public void RemoveFieldsNotInList_corrects_case_of_field_name()
        {
            var fields = new List<SharePointField> { new SharePointField { StaticName = "Title" }, new SharePointField { StaticName = "ID" } };
            var fieldNames = new List<string> { "title", "Id", };

            var result = fieldNames.RemoveFieldsNotInList(fields).ToList();

            Assert.AreEqual(2, result.Count());
            Assert.AreEqual("Title", result[0]);
            Assert.AreEqual("ID", result[1]);
        }

        [TestMethod]
        public void RemoveFieldsNotInList_returns_empty_list_when_fields_list_is_empty()
        {
            var fields = new List<SharePointField>();
            var fieldNames = new List<string> { "Title", "ID", "ExtraField" };

            var result = fieldNames.RemoveFieldsNotInList(fields).ToList();

            Assert.AreEqual(0, result.Count());
        }

        [TestMethod]
        public void RemoveFieldsNotInList_removes_items_not_in_list_when_names_differ_by_case()
        {
            var fields = new List<SharePointField> { new SharePointField { StaticName = "Title" }, new SharePointField { StaticName = "ID" } };
            var fieldNames = new List<string> { "title", "Id", "ExtraField" };

            var result = fieldNames.RemoveFieldsNotInList(fields).ToList();

            Assert.AreEqual(2, result.Count());
            Assert.AreEqual("Title", result[0]);
            Assert.AreEqual("ID", result[1]);
        }

        [TestMethod]
        public void RemoveFieldsNotInList_returns_all_items_when_field_list_is_null()
        {
            List<SharePointField> fields = null;
            var fieldNames = new List<string> { "Title", "ID", "ExtraField" };

            var result = fieldNames.RemoveFieldsNotInList(fields).ToList();

            Assert.AreEqual(3, result.Count());
            Assert.AreEqual("Title", result[0]);
            Assert.AreEqual("ID", result[1]);
            Assert.AreEqual("ExtraField", result[2]);
        }

        [TestMethod]
        public void RemoveFieldsNotInList_returns_null_when_field_names_list_is_null()
        {
            List<SharePointField> fields = null;
            List<string> fieldNames = null;

            var result = fieldNames.RemoveFieldsNotInList(fields);

            Assert.IsNull(result);
        }

        [TestMethod]
        public void String_ToViewFieldsXElement_should_correctly_parse_string()
        {
            var xmlString = "<ViewFields><FieldRef Name=\"ID\" /><FieldRef Name=\"Title\" /></ViewFields>";
            var viewFields = xmlString.ToViewFieldsXElement();
            var list = viewFields.Descendants().Where(e => e.Name.LocalName == "FieldRef").ToList();
            Assert.AreEqual(2, list.Count);
            Assert.AreEqual("ID", list[0].Attribute("Name").Value);
            Assert.AreEqual("Title", list[1].Attribute("Name").Value);
        }

        [TestMethod]
        public void String_ToViewFieldsXElement_should_correctly_parse_string_when_xml_element_names_differ_by_case()
        {
            var xmlString = "<ViewFields><fieldref Name=\"ID\" /><FieldRef name=\"Title\" /></ViewFields>";
            var viewFields = xmlString.ToViewFieldsXElement();
            var list = viewFields.Descendants().Where(e => e.Name.LocalName == "FieldRef").ToList();
            Assert.AreEqual(2, list.Count);
            Assert.AreEqual("ID", list[0].Attribute("Name").Value);
            Assert.AreEqual("Title", list[1].Attribute("Name").Value);
        }

        [TestMethod]
        public void String_ToViewFieldsXElement_with_field_list_should_remove_fields_not_in_list()
        {
            var fields = new List<SharePointField> { new SharePointField { StaticName = "Title" }, new SharePointField { StaticName = "ID" } };
            var xmlString = "<ViewFields><FieldRef Name=\"ID\" /><FieldRef Name=\"Title\" /><FieldRef Name=\"Extra\" /></ViewFields>";
            var viewFields = xmlString.ToViewFieldsXElement(fields);
            var list = viewFields.Descendants().Where(e => e.Name.LocalName == "FieldRef").ToList();
            Assert.AreEqual(2, list.Count);
            Assert.AreEqual("ID", list[0].Attribute("Name").Value);
            Assert.AreEqual("Title", list[1].Attribute("Name").Value);

        }

        [TestMethod]
        public void String_ToViewFieldsXElement_with_field_list_should_remove_fields_not_in_list_when_differs_by_case()
        {
            var fields = new List<SharePointField> { new SharePointField { StaticName = "Title" }, new SharePointField { StaticName = "ID" } };
            var xmlString = "<ViewFields><FieldRef Name=\"id\" /><FieldRef Name=\"title\" /><FieldRef Name=\"Extra\" /></ViewFields>";
            var viewFields = xmlString.ToViewFieldsXElement(fields);
            var list = viewFields.Descendants().Where(e => e.Name.LocalName == "FieldRef").ToList();
            Assert.AreEqual(2, list.Count);
            Assert.AreEqual("ID", list[0].Attribute("Name").Value);
            Assert.AreEqual("Title", list[1].Attribute("Name").Value);

        }

        [TestMethod]
        public void String_ToViewFieldsXElement_should_remove_duplicates()
        {
            var xmlString = "<ViewFields><FieldRef Name=\"ID\" /><FieldRef Name=\"Title\" /><FieldRef Name=\"Title\" /><FieldRef Name=\"Title\" /></ViewFields>";
            var viewFields = xmlString.ToViewFieldsXElement();
            var list = viewFields.Descendants().Where(e => e.Name.LocalName == "FieldRef").ToList();
            Assert.AreEqual(2, list.Count);
        }

        [TestMethod]
        public void String_ToViewFieldsXElement_should_remove_duplicates_when_names_differ_by_case()
        {
            var xmlString = "<ViewFields><FieldRef Name=\"ID\" /><FieldRef Name=\"TiTle\" /><FieldRef Name=\"title\" /><FieldRef Name=\"TITLE\" /></ViewFields>";
            var viewFields = xmlString.ToViewFieldsXElement();
            var list = viewFields.Descendants().Where(e => e.Name.LocalName == "FieldRef").ToList();
            Assert.AreEqual(2, list.Count);
        }

        [TestMethod]
        public void String_ToViewFieldsXElement_should_return_empty_viewfields_element_when_input_is_empty_string()
        {
            var xmlString = string.Empty;
            var viewFields = xmlString.ToViewFieldsXElement();
            Assert.AreEqual("<ViewFields />", viewFields.ToString());
        }

        [TestMethod]
        public void String_ToViewFieldsXElement_should_return_empty_viewfields_element_when_input_is_null()
        {
            string xmlString = null;
            var viewFields = xmlString.ToViewFieldsXElement();
            Assert.AreEqual("<ViewFields />", viewFields.ToString());
        }

        [TestMethod]
        public void IEnumerable_ToViewFieldsXElement_should_correctly_convert_to_viewfields_element()
        {
            var fieldNames = new List<string> {"ID", "Title"};
            var viewFields = fieldNames.ToViewFieldsXElement();
            var list = viewFields.Descendants().Where(e => e.Name.LocalName == "FieldRef").ToList();
            Assert.AreEqual(2, list.Count);
            Assert.AreEqual("ID", list[0].Attribute("Name").Value);
            Assert.AreEqual("Title", list[1].Attribute("Name").Value);
        }

        [TestMethod]
        public void IEnumerable_ToViewFieldsXElement_with_field_list_should_remove_items_not_in_field_list()
        {
            var fields = new List<SharePointField> { new SharePointField { StaticName = "Title" }, new SharePointField { StaticName = "ID" } };

            var fieldNames = new List<string> { "ID", "Title", "ExtraField" };
            var viewFields = fieldNames.ToViewFieldsXElement(fields);
            var list = viewFields.Descendants().Where(e => e.Name.LocalName == "FieldRef").ToList();
            Assert.AreEqual(2, list.Count);
            Assert.AreEqual("ID", list[0].Attribute("Name").Value);
            Assert.AreEqual("Title", list[1].Attribute("Name").Value);

        }

        [TestMethod]
        public void IEnumerable_ToViewFieldsXElement_should_remove_duplicates()
        {
            var fieldNames = new List<string> { "ID", "Title", "Title" };
            var viewFields = fieldNames.ToViewFieldsXElement();
            var list = viewFields.Descendants().Where(e => e.Name.LocalName == "FieldRef").ToList();
            Assert.AreEqual(2, list.Count);
        }

        [TestMethod]
        public void IEnumerable_ToViewFieldsXElement_should_remove_duplicates_when_names_differ_by_case()
        {
            var fieldNames = new List<string> { "ID", "Title", "TiTle", "TITLE" };
            var viewFields = fieldNames.ToViewFieldsXElement();
            var list = viewFields.Descendants().Where(e => e.Name.LocalName == "FieldRef").ToList();
            Assert.AreEqual(2, list.Count);
        }

        [TestMethod]
        public void IEnumerable_ToViewFieldsXElement_should_return_empty_viewfields_element_when_input_is_null()
        {
            List<string> fieldNames = null;
            var viewFields = fieldNames.ToViewFieldsXElement();
            Assert.AreEqual("<ViewFields />", viewFields.ToString());

        }

        [TestMethod]
        public void IEnumerable_ToViewFieldsXElement_should_return_empty_viewfields_element_when_input_is_empty_list()
        {
            List<string> fieldNames = new List<string>();
            var viewFields = fieldNames.ToViewFieldsXElement();
            Assert.AreEqual("<ViewFields />", viewFields.ToString());

        }

        [TestMethod]
        public void FindByStaticName_should_find_element()
        {
            var fields = new List<SharePointField>
                             {new SharePointField {StaticName = "Title"}, new SharePointField {StaticName = "ID"}};

            var field = fields.FindByStaticName("ID");
            Assert.IsNotNull(field);
            Assert.AreEqual("ID", field.StaticName);
        }

        [TestMethod]
        public void FindByStaticName_should_return_null_when_not_found()
        {
            var fields = new List<SharePointField> { new SharePointField { StaticName = "Title" }, new SharePointField { StaticName = "ID" } };

            var field = fields.FindByStaticName("NotFound");
            Assert.IsNull(field);
        }

        [TestMethod]
        public void FindByStaticName_should_return_null_when_input_is_null()
        {
            List<SharePointField> fields = null;
            var field = fields.FindByStaticName("NotFound");
            Assert.IsNull(field);
        }
    }
}
